#include "string2.h"
#include "vector.h"

Vector::Vector ()
{
  size = 5;
  inc = 5;
  pos = 0;
}

Vector::Vector (string obj_name, int max_size = 5)
{
  if (max_size > 0)
	size = max_size;
  else
	size = 5;

  name = obj_name;
  pos = 0;
  inc = 5;
}

string Vector::set_name (string new_name)
{
  name = new_name;
  return name;
}

string Vector::get_name ()
{
  return name;
}

Numvec::Numvec () : Vector ()
{
  data_vec = new float[size];
  max = 0;
  min = 0;
  name = "Numvec";
  for (int i = 0; i < size; i++)
	data_vec[i] = 0;
  type = numvec;
}

Numvec::Numvec (string obj_name, float max_val, float min_val, int max_size = 5) : Vector (obj_name, max_size)
{
  data_vec = new float[size];
  max = max_val;
  min = min_val;
  if (max_val < min_val)
  { // if the max_value < min_value, then the values are switched
	max = min_val;
	min = max_val;
  }

  for (int i = 0; i < size; i++)
	data_vec[i] = 0.0;
  type = numvec;
}

Numvec::Numvec (const Numvec& a)
{
  copy (a);
}    

Numvec::~Numvec ()
{
  delete [] data_vec;
}

boolean Numvec::set_min (float new_min)
{
  if (new_min > min)
  {
	cout << "Cannot set a larger mininum value! Mininum value not changed!" << endl;
	return FALSE;
  }
  else
  {
	min = new_min;
	return TRUE;
  }
}

float Numvec::get_min ()
{
  return min;
}

boolean Numvec::set_max (float new_max)
{
  if (new_max < max)
  {
	cout << "Cannnot set a smaller maxium! Maxium value not changed!" << endl;
	return FALSE;
  }
  else
  {
	max = new_max;
	return TRUE;
  }
}

float Numvec::get_max ()
{
  return max;
}

boolean Numvec::add_item (string data)
{
  float temp;

  if (pos == size)	  // if the current array is full
  {
	size += inc;
	if (!expand_vector ())    // try to expand the memory
	  return FALSE; 	  // out of memory
  }

  if (data.is_float())
  {
	temp = float (data);
	if ((temp < min) || (temp > max))
	  return FALSE;           // data outside the range
	else
	{
	  data_vec[pos++] = temp;
	  return TRUE;
	}
  }
  else
	return FALSE;            // the string cannot be converted to a float
}

float Numvec::get (int num)
{
  if ((num < 1) || (num > pos))
	return -1;
  else
	return data_vec[num - 1];
}

int Numvec::get_size ()
{
  return pos;		// pos points to the next available space to store a new
			// data, but since the array index starts from 0, pos also
			// equal the number of items in the array.
}

boolean Numvec::valid (float num)
{
  if ((num >= min) && (num <= max))
	return TRUE;
  else
	return FALSE;
}

void Numvec::print ()
{
  cout << "Content of " << name << ": ";
  for (int i = 0; i < pos; i++)
	cout << data_vec[i] << " ";
  cout << endl;
}

type_of_vec Numvec::get_type ()
{
  return type;
}

boolean Numvec::expand_vector ()
{
  float *temp;
  int i;

  if (!(temp = new float[size]))
	return FALSE;		// insufficient memory

  for (i = 0; i < pos; i++)
	temp[i] = data_vec[i];

  for (i = pos; i < size; i++)
	temp[i] = 0.0;
  delete [] data_vec;		// delete old vector
  data_vec = temp;
  cout << "Array expanded..." << endl;
  return TRUE;
}

void Numvec::copy (const Numvec& a)
{
  name = a.name;
  max = a.max;
  min = a.min;
  size = a.size;
  inc = a.inc;
  pos = a.pos;
  data_vec = new float[size];
  for (int i = 0; i < size; i++)
	data_vec[i] = a.data_vec[i];
  type = a.type;
}

Numvec& Numvec::operator= (const Numvec& a)
{
  if (&a != this)
  { // if the assignment is not a = a
	delete [] data_vec;
	copy (a);
  }
  return *this;
}

Codevec::Codevec () : Vector ()
{
  int i;

  name = "Codevec";
  allowed_pos =  0;
  allowed_size = 5;
  data_vec = new string[size];
  allowed = new string[allowed_size];
  type = codevec;

  for (i = 0; i < size; i++)
	data_vec[i] = allowed[i] = "";  // initialize the two arrays to null strings
}

Codevec::Codevec (string obj_name, int max_size) : Vector (obj_name, max_size)
{
  int i;

  name = obj_name;
  allowed_pos = pos = 0;
  allowed_size = 5;
  data_vec = new string[size];
  allowed = new string[allowed_size];
  for (i = 0; i < size; i++)
	allowed[i] = data_vec[i] = "";
	type = codevec;
}

Codevec::Codevec (const Codevec& a)
{
  copy (a);
}


Codevec::~Codevec ()
{
  delete [] data_vec;
  delete [] allowed;
}

boolean Codevec::add_item (string data)
{
  if (!valid (data))		// if data is not one of the allowable string
	return FALSE;
  else
	if (pos == size)
	{ // array is full
	  size += inc;
	  if (!expand_vector (data_vector))  // try to expand the array
	  {
		cout << "Out of memory! No new data added" << endl;
		return FALSE;
	  }
	}
  data_vec[pos++] = data;
  return TRUE;
}

int Codevec::get_size ()
{
  return pos;	// pos points to the next available position to store data in the
  		// array which equals the number of items in the array
}

string Codevec::get (int num)
{
  if ((num < 1) || (num > pos))
	return "";
  else
	return data_vec [num - 1];
}

boolean Codevec::add_allowed (string allow)
{
  if (valid (allow))		 // string allow exist in allowed array
	return FALSE;
  else
	if (allowed_pos == allowed_size) // if the array is full and need to expand
	{
	  allowed_size += inc;
	  if (!expand_vector (allow_vector)) // if there is insufficient memory space
		return FALSE;
	}
	
  allowed[allowed_pos++] = allow;
  return TRUE;
}

void Codevec::print ()
{
  cout << "Vector " << name << ": " << endl;
  for (int i = 0; i < pos; i++)
	cout << data_vec[i] << endl;
}

void Codevec::display_allowed ()
{
  cout << "Allowable strings for " << name << ": " << endl;
  for (int i = 0; i < allowed_pos; i++)
	cout << allowed[i] << endl;
}

boolean Codevec::valid (string check)
{
  for (int i = 0; i < allowed_pos; i++)
	if (allowed[i] == check)
	  return TRUE;
  return FALSE;		// string not found in the allowable string array
}

type_of_vec Codevec::get_type ()
{
  return type;
}

boolean Codevec::expand_vector (vec_type type)
{
  string *temp;
  int i;

  if (!(temp = new string[size]))  // insufficient memory space
	return FALSE;

  if (type)
  {  // if type is allow_vec
	for (i = 0; i < allowed_pos; i++)
	  temp[i] = allowed[i];
	for (i = allowed_pos; i < allowed_size; i++)
	  temp[i] = "";
	delete [] allowed;
	allowed = temp;
  }
  else
  { // if type is data_vec
	for (i = 0; i < pos; i++)
	  temp[i] = data_vec[i];
	for (i = pos; i < size; i++)
	  temp[i] = "";
	delete [] data_vec;
	data_vec = temp;
  }
  cout << "Array expanded..." << endl;
  return TRUE;
}

void Codevec::copy (const Codevec& a)
{
  int i;

  name = a.name;
  type = a.type;
  size = a.size;
  allowed_size = a.allowed_size;
  inc = a.inc;
  pos = a.pos;
  allowed_pos = a.allowed_pos;
  data_vec = new string[size];
  allowed = new string[allowed_size];
  for (i = 0; i < size; i++)
	data_vec[i] = a.data_vec[i];
  for (i = 0; i < allowed_size; i++)
	allowed[i] = a.allowed[i];
}

Codevec& Codevec::operator= (const Codevec& a)
{
  if (&a != this)
  { // if the assignment is not a = a
	delete [] data_vec;
	delete [] allowed;
	copy (a);
  }
  return *this;
}